home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / OpenGL / OPENGL2.EXE / _SETUP.1 / vcull.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-21  |  23.0 KB  |  963 lines

  1. /*
  2. ** Vertex Culling Test
  3. */
  4. #include <windows.h>
  5. #include <math.h>
  6. #include <GL/gl.h>
  7.  
  8. #if defined(GL_SGI_cull_vertex)
  9. PFNGLCULLPARAMETERFVSGIPROC CullParameterfv;
  10. #endif
  11.  
  12. #if defined(GL_SGI_compiled_vertex_array)
  13. PFNGLLOCKARRAYSSGIPROC LockArrays;
  14. PFNGLUNLOCKARRAYSSGIPROC UnlockArrays;
  15. #endif
  16.  
  17. #if !defined(M_PI)
  18. #define M_PI 3.14159265F
  19. #endif
  20.  
  21. char *className = "OpenGL";
  22. char *windowName = "Vertex Culling Test";
  23. int winX, winY;
  24. int winWidth, winHeight;
  25.  
  26. HDC hDC;
  27. HGLRC hGLRC;
  28. HPALETTE hPalette;
  29.  
  30. void (*idleFunc)(void);
  31.  
  32. GLfloat objectXform[4][4];
  33. float angle = 10.0F, axis[3] = { 0.0F, 0.0F, 1.0F };
  34.  
  35. void drawCube(void);
  36. void drawTorus(void);
  37. void drawSphere(void);
  38. #define NUM_OBJECTS (sizeof(drawObject) / sizeof(drawObject[0]))
  39. void (*drawObject[])(void) = {
  40.     drawTorus, drawSphere, drawCube,
  41. };
  42. int objectIndex;
  43.  
  44. int objectNumMajor = 24, objectNumMinor = 32;
  45. BOOL halfObject = FALSE;
  46. BOOL redrawContinue = TRUE;
  47. BOOL doubleBuffered = TRUE;
  48. BOOL depthBuffered = TRUE;
  49. BOOL drawOutlines = FALSE;
  50. BOOL textureEnabled = FALSE;
  51. BOOL textureReplace = FALSE;
  52. BOOL useVertexCull = TRUE;
  53. BOOL useFaceCull = TRUE;
  54. BOOL useVertexArray = TRUE;
  55. BOOL useVertexLocking = TRUE;
  56. BOOL useLighting = TRUE;
  57. BOOL perspectiveProj = TRUE;
  58. BOOL useFog = FALSE;
  59. enum MoveModes { MoveNone, MoveObject };
  60. enum MoveModes mode = MoveObject;
  61.  
  62. #define X_OFFSET_STEP 0.025F;
  63. #define Y_OFFSET_STEP 0.025F;
  64. GLfloat xOffset, yOffset;
  65.  
  66. void
  67. drawCube(void)
  68. {
  69.     glBegin(GL_QUADS);
  70.     glNormal3f(-1.0F, 0.0F, 0.0F);
  71.     glTexCoord2f( 0.0F, 1.0F); glVertex3f(-0.5F,-0.5F,-0.5F);
  72.     glTexCoord2f( 0.0F, 0.0F); glVertex3f(-0.5F,-0.5F, 0.5F);
  73.     glTexCoord2f( 1.0F, 0.0F); glVertex3f(-0.5F, 0.5F, 0.5F);
  74.     glTexCoord2f( 1.0F, 1.0F); glVertex3f(-0.5F, 0.5F,-0.5F);
  75.  
  76.     glNormal3f( 1.0F, 0.0F, 0.0F);
  77.     glTexCoord2f( 1.0F, 1.0F); glVertex3f( 0.5F, 0.5F, 0.5F);
  78.     glTexCoord2f( 0.0F, 1.0F); glVertex3f( 0.5F,-0.5F, 0.5F);
  79.     glTexCoord2f( 0.0F, 0.0F); glVertex3f( 0.5F,-0.5F,-0.5F);
  80.     glTexCoord2f( 1.0F, 0.0F); glVertex3f( 0.5F, 0.5F,-0.5F);
  81.  
  82.     glNormal3f( 0.0F,-1.0F, 0.0F);
  83.     glTexCoord2f( 0.0F, 1.0F); glVertex3f(-0.5F,-0.5F,-0.5F);
  84.     glTexCoord2f( 0.0F, 0.0F); glVertex3f( 0.5F,-0.5F,-0.5F);
  85.     glTexCoord2f( 1.0F, 0.0F); glVertex3f( 0.5F,-0.5F, 0.5F);
  86.     glTexCoord2f( 1.0F, 1.0F); glVertex3f(-0.5F,-0.5F, 0.5F);
  87.  
  88.     glNormal3f( 0.0F, 1.0F, 0.0F);
  89.     glTexCoord2f( 1.0F, 1.0F); glVertex3f( 0.5F, 0.5F, 0.5F);
  90.     glTexCoord2f( 0.0F, 1.0F); glVertex3f( 0.5F, 0.5F,-0.5F);
  91.     glTexCoord2f( 0.0F, 0.0F); glVertex3f(-0.5F, 0.5F,-0.5F);
  92.     glTexCoord2f( 1.0F, 0.0F); glVertex3f(-0.5F, 0.5F, 0.5F);
  93.  
  94.     glNormal3f( 0.0F, 0.0F,-1.0F);
  95.     glTexCoord2f( 0.0F, 1.0F); glVertex3f(-0.5F,-0.5F,-0.5F);
  96.     glTexCoord2f( 0.0F, 0.0F); glVertex3f(-0.5F, 0.5F,-0.5F);
  97.     glTexCoord2f( 1.0F, 0.0F); glVertex3f( 0.5F, 0.5F,-0.5F);
  98.     glTexCoord2f( 1.0F, 1.0F); glVertex3f( 0.5F,-0.5F,-0.5F);
  99.  
  100.     glNormal3f( 0.0F, 0.0F, 1.0F);
  101.     glTexCoord2f( 1.0F, 1.0F); glVertex3f( 0.5F, 0.5F, 0.5F);
  102.     glTexCoord2f( 0.0F, 1.0F); glVertex3f(-0.5F, 0.5F, 0.5F);
  103.     glTexCoord2f( 0.0F, 0.0F); glVertex3f(-0.5F,-0.5F, 0.5F);
  104.     glTexCoord2f( 1.0F, 0.0F); glVertex3f( 0.5F,-0.5F, 0.5F);
  105.     glEnd();
  106. }
  107.  
  108. void
  109. drawTorus(void)
  110. {
  111.     struct vertex {
  112.         GLfloat t[2];
  113.     GLfloat n[3];
  114.     GLfloat v[3];
  115.     };
  116.  
  117.     int numVerts = (objectNumMajor+1) * (objectNumMinor+1);
  118.     int numStrips = halfObject ? objectNumMajor / 2 : objectNumMajor;
  119.     int numPerStrip = 2 * (objectNumMinor+1);
  120.     int numElements = (objectNumMajor+1) * numPerStrip;
  121.  
  122.     static struct vertex *vertexArray, *v;
  123.     static GLuint *elementArray, *e;
  124.     static int numMajor;
  125.     static int numMinor;
  126.     int i, j;
  127.  
  128.     if (!vertexArray || numMajor!=objectNumMajor || numMinor!=objectNumMinor) {
  129.     float majorRadius = 0.6F;
  130.     float minorRadius = 0.2F;
  131.     double majorStep = 2.0F*M_PI / objectNumMajor;
  132.     double minorStep = 2.0F*M_PI / objectNumMinor;
  133.  
  134.     if (vertexArray) free(vertexArray);
  135.     vertexArray = (struct vertex *)
  136.         calloc(numVerts, sizeof(struct vertex));
  137.  
  138.     if (elementArray) free(elementArray);
  139.     elementArray = (GLuint *)
  140.         calloc(numElements, sizeof(GLuint));
  141.  
  142.     numMajor = objectNumMajor;
  143.     numMinor = objectNumMinor;
  144.  
  145.     v = vertexArray;
  146.     e = elementArray;
  147.     for (i=0; i<=numMajor; ++i) {
  148.         double a = i * majorStep;
  149.         GLfloat x = (GLfloat) cos(a);
  150.         GLfloat y = (GLfloat) sin(a);
  151.  
  152.         for (j=0; j<=numMinor; ++j) {
  153.         double b = j * minorStep;
  154.         GLfloat c = (GLfloat) cos(b);
  155.         GLfloat r = minorRadius * c + majorRadius;
  156.         GLfloat z = minorRadius * (GLfloat) sin(b);
  157.  
  158.         v->t[0] = i/(GLfloat) numMajor;
  159.         v->t[1] = j/(GLfloat) numMinor;
  160.  
  161.         v->n[0] = x*c;
  162.         v->n[1] = y*c;
  163.         v->n[2] = z/minorRadius;
  164.  
  165.         v->v[0] = x*r;
  166.         v->v[1] = y*r;
  167.         v->v[2] = z;
  168.  
  169.         v++;
  170.  
  171.         *e++ = i * (numMinor+1) + j;
  172.         *e++ = (i+1) * (numMinor+1) + j;
  173.         }
  174.     }
  175.     }
  176.  
  177.     if (useVertexArray) {
  178.     glInterleavedArrays(GL_T2F_N3F_V3F, 0, vertexArray);
  179.  
  180. #if defined(GL_SGI_compiled_vertex_array)
  181.     if (useVertexLocking && LockArrays) LockArrays(0, numVerts);
  182. #endif
  183.  
  184.     for (i=0, e=elementArray; i<numStrips; ++i, e+=numPerStrip) {
  185.         glDrawElements(GL_TRIANGLE_STRIP, numPerStrip, GL_UNSIGNED_INT, e);
  186.     }
  187.  
  188. #if defined(GL_SGI_compiled_vertex_array)
  189.     if (useVertexLocking && UnlockArrays) UnlockArrays();
  190. #endif
  191.     } else {
  192.     for (i=0, e=elementArray; i<numStrips; ++i, e+=numPerStrip) {
  193.         glBegin(GL_TRIANGLE_STRIP);
  194.         for (j=0; j<numPerStrip; ++j) {
  195.         v = &vertexArray[e[j]];
  196.  
  197.         glTexCoord2fv(v->t);
  198.         glNormal3fv(v->n);
  199.         glVertex3fv(v->v);
  200.         }
  201.         glEnd();
  202.     }
  203.     }
  204. }
  205.  
  206. void
  207. drawSphere(void)
  208. {
  209.     struct vertex {
  210.         GLfloat t[2];
  211.     GLfloat n[3];
  212.     GLfloat v[3];
  213.     };
  214.  
  215.     int numVerts = (objectNumMajor+1) * (objectNumMinor+1);
  216.     int numStrips = halfObject ? objectNumMajor / 2 : objectNumMajor;
  217.     int numPerStrip = 2 * (objectNumMinor+1);
  218.     int numElements = (objectNumMajor+1) * numPerStrip;
  219.  
  220.     static struct vertex *vertexArray, *v;
  221.     static GLuint *elementArray, *e;
  222.     static int numMajor;
  223.     static int numMinor;
  224.     int i, j;
  225.  
  226.     if (!vertexArray || numMajor!=objectNumMajor || numMinor!=objectNumMinor) {
  227.     float radius = 0.6F;
  228.     double majorStep = 2.0F*M_PI / objectNumMajor;
  229.     double minorStep = M_PI / objectNumMinor;
  230.  
  231.     if (vertexArray) free(vertexArray);
  232.     vertexArray = (struct vertex *)
  233.         calloc(numVerts, sizeof(struct vertex));
  234.  
  235.     if (elementArray) free(elementArray);
  236.     elementArray = (GLuint *)
  237.         calloc(numElements, sizeof(GLuint));
  238.  
  239.     numMajor = objectNumMajor;
  240.     numMinor = objectNumMinor;
  241.  
  242.     v = vertexArray;
  243.     e = elementArray;
  244.     for (i=0; i<=numMajor; ++i) {
  245.         double a = i * majorStep;
  246.         GLfloat x = (GLfloat) cos(a);
  247.         GLfloat y = (GLfloat) sin(a);
  248.  
  249.         for (j=0; j<=numMinor; ++j) {
  250.         double b = j * minorStep;
  251.         GLfloat c = (GLfloat) sin(b);
  252.         GLfloat r = c * radius;
  253.         GLfloat z = (GLfloat) cos(b);
  254.  
  255.         v->t[0] = i/(GLfloat) numMajor;
  256.         v->t[1] = j/(GLfloat) numMinor;
  257.  
  258.         v->n[0] = x*c;
  259.         v->n[1] = y*c;
  260.         v->n[2] = z;
  261.  
  262.         v->v[0] = x*r;
  263.         v->v[1] = y*r;
  264.         v->v[2] = z*radius;
  265.  
  266.         v++;
  267.  
  268.         *e++ = (i+1) * (numMinor+1) + j;
  269.         *e++ = i * (numMinor+1) + j;
  270.         }
  271.     }
  272.     }
  273.  
  274.     if (useVertexArray) {
  275.     glInterleavedArrays(GL_T2F_N3F_V3F, 0, vertexArray);
  276.  
  277. #if defined(GL_SGI_compiled_vertex_array)
  278.     if (useVertexLocking && LockArrays) LockArrays(0, numVerts);
  279. #endif
  280.  
  281.     for (i=0, e=elementArray; i<numStrips; ++i, e+=numPerStrip) {
  282.         glDrawElements(GL_TRIANGLE_STRIP, numPerStrip, GL_UNSIGNED_INT, e);
  283.     }
  284.  
  285. #if defined(GL_SGI_compiled_vertex_array)
  286.     if (useVertexLocking && UnlockArrays) UnlockArrays();
  287. #endif
  288.     } else {
  289.     for (i=0, e=elementArray; i<numStrips; ++i, e+=numPerStrip) {
  290.         glBegin(GL_TRIANGLE_STRIP);
  291.         for (j=0; j<numPerStrip; ++j) {
  292.         v = &vertexArray[e[j]];
  293.  
  294.         glTexCoord2fv(v->t);
  295.         glNormal3fv(v->n);
  296.         glVertex3fv(v->v);
  297.         }
  298.         glEnd();
  299.     }
  300.     }
  301. }
  302.  
  303. void
  304. setCheckTexture(void)
  305. {
  306.     int texWidth = 256;
  307.     int texHeight = 256;
  308.     GLubyte *texPixels, *p;
  309.     int texSize;
  310.     int i, j;
  311.  
  312.     texSize = texWidth*texHeight*4*sizeof(GLubyte);
  313.     if (textureReplace) {
  314.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  315.     } else {
  316.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  317.     }
  318.  
  319.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  320.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  321.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  322.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  323.  
  324.     texPixels = (GLubyte *) malloc(texSize);
  325.     if (texPixels == NULL) {
  326.     return;
  327.     }
  328.  
  329.     p = texPixels;
  330.     for (i=0; i<texHeight; ++i) {
  331.     for (j=0; j<texWidth; ++j) {
  332.         if ((i ^ j) & 32) {
  333.         p[0] = 0xff; p[1] = 0xff; p[2] = 0xff; p[3] = 0xff;
  334.         } else {
  335.         p[0] = 0x10; p[1] = 0x10; p[2] = 0x10; p[3] = 0xff;
  336.         }
  337.         p += 4;
  338.     }
  339.     }
  340.  
  341.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
  342.          texWidth, texHeight, 0,
  343.          GL_RGBA, GL_UNSIGNED_BYTE, texPixels);
  344.  
  345.     free(texPixels);
  346. }
  347.  
  348. void
  349. matrixIdentity(GLfloat m[4][4])
  350. {
  351.     m[0][0] = 1.0F; m[0][1] = 0.0F; m[0][2] = 0.0F; m[0][3] = 0.0F;
  352.     m[1][0] = 0.0F; m[1][1] = 1.0F; m[1][2] = 0.0F; m[1][3] = 0.0F;
  353.     m[2][0] = 0.0F; m[2][1] = 0.0F; m[2][2] = 1.0F; m[2][3] = 0.0F;
  354.     m[3][0] = 0.0F; m[3][1] = 0.0F; m[3][2] = 0.0F; m[3][3] = 1.0F;
  355. }
  356.  
  357. void
  358. setProjection(void)
  359. {
  360.     GLfloat aspect = (GLfloat) winWidth / (GLfloat) winHeight;
  361.  
  362.     glMatrixMode(GL_PROJECTION);
  363.     glLoadIdentity();
  364.     if (perspectiveProj) {
  365.     glFrustum(-0.5F*aspect, 0.5F*aspect, -0.5F, 0.5F, 1.0F, 3.0F);
  366.  
  367. #if defined(GL_SGI_cull_vertex)
  368.     if (CullParameterfv) {
  369.         GLfloat eye[4] = { 0.0F, 0.0F, 0.0F, 1.0F };
  370.  
  371.         CullParameterfv(GL_CULL_VERTEX_EYE_POSITION_SGI, eye);
  372.     }
  373. #endif
  374.     } else {
  375.     glOrtho(-1.0F*aspect, 1.0F*aspect, -1.0F, 1.0F, 1.0F, 3.0F);
  376.  
  377. #if defined(GL_SGI_cull_vertex)
  378.     if (CullParameterfv) {
  379.         GLfloat eye[4] = { 0.0F, 0.0F, 1.0F, 0.0F };
  380.  
  381.         CullParameterfv(GL_CULL_VERTEX_EYE_POSITION_SGI, eye);
  382.     }
  383. #endif
  384.     }
  385.     glMatrixMode(GL_MODELVIEW);
  386. }
  387.  
  388. void
  389. setMaterial(void)
  390. {
  391.     GLfloat matAmb[4] = { 0.01F, 0.01F, 0.01F, 1.00F };
  392.     GLfloat matDiff[4] = { 0.45F, 0.05F, 0.65F, 0.60F };
  393.     GLfloat matSpec[4] = { 0.50F, 0.50F, 0.50F, 1.00F };
  394.     GLfloat matShine = 20.00F;
  395.  
  396.     glMaterialfv(GL_FRONT, GL_AMBIENT, matAmb);
  397.     glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff);
  398.     glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec);
  399.     glMaterialf(GL_FRONT, GL_SHININESS, matShine);
  400. }
  401.  
  402. void
  403. init(void)
  404. {
  405.     GLfloat light0Pos[4] = { 0.70F, 0.70F, 1.25F, 0.00F };
  406.     GLfloat fogDensity = 2.35F*0.180F;
  407.     GLfloat fogColor[4] = {
  408.     0.4F, 0.4F, 0.5F, 1.0F,
  409.     };
  410.  
  411. #if defined(GL_SGI_cull_vertex)
  412.     CullParameterfv = (PFNGLCULLPARAMETERFVSGIPROC)
  413.         wglGetProcAddress("glCullParameterfvSGI");
  414. #endif
  415.  
  416. #if defined(GL_SGI_compiled_vertex_array)
  417.     LockArrays = (PFNGLLOCKARRAYSSGIPROC)
  418.         wglGetProcAddress("glLockArraysSGI");
  419.     UnlockArrays = (PFNGLUNLOCKARRAYSSGIPROC)
  420.         wglGetProcAddress("glUnlockArraysSGI");
  421. #endif
  422.  
  423.     glFogi(GL_FOG_MODE, GL_EXP2);
  424.     glFogf(GL_FOG_DENSITY, fogDensity);
  425.     glFogfv(GL_FOG_COLOR, fogColor);
  426.  
  427.     setProjection();
  428.     glTranslatef(0.0F, 0.0F, -2.0F);
  429.  
  430.     setMaterial();
  431.  
  432.     glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
  433.     glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
  434.     glEnable(GL_LIGHT0);
  435.  
  436.     setCheckTexture();
  437.  
  438.     matrixIdentity(objectXform);
  439. }
  440.  
  441. void
  442. resize(void)
  443. {
  444.     setProjection();
  445.     glViewport(0, 0, winWidth, winHeight);
  446. }
  447.  
  448. void
  449. doRedraw(void)
  450. {
  451.     if (useFog) {
  452.     glClearColor(0.4F, 0.4F, 0.5F, 1.0F);
  453.     glEnable(GL_FOG);
  454.     } else {
  455.     glClearColor(0.2F, 0.2F, 0.1F, 1.0F);
  456.     glDisable(GL_FOG);
  457.     }
  458.  
  459.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  460.  
  461.     /* update transformations */
  462.     if (mode == MoveObject) {
  463.     glPushMatrix();
  464.     glLoadIdentity();
  465.     glRotatef(angle, axis[0], axis[1], axis[2]);
  466.     glMultMatrixf((GLfloat *) objectXform);
  467.     glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) objectXform);
  468.     glPopMatrix();
  469.     }
  470.  
  471.     if (textureEnabled) {
  472.     glEnable(GL_TEXTURE_2D);
  473.     }
  474.     if (drawOutlines) {
  475.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  476.     }
  477. #if defined(GL_SGI_cull_vertex)
  478.     if (useVertexCull) {
  479.         glEnable(GL_CULL_VERTEX_SGI);
  480.     }
  481. #endif
  482.     if (useFaceCull) {
  483.         glEnable(GL_CULL_FACE);
  484.     }
  485.     if (useLighting) {
  486.     glEnable(GL_LIGHTING);
  487.     }
  488.     glEnable(GL_DEPTH_TEST);
  489.  
  490.     glPushMatrix();
  491.     glTranslatef(xOffset, yOffset, 0.0F);
  492.     glMultMatrixf((GLfloat *) objectXform);
  493.  
  494.     (*drawObject[objectIndex])();
  495.  
  496.     glPopMatrix();
  497.  
  498.     glDisable(GL_TEXTURE_2D);
  499.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  500. #if defined(GL_SGI_cull_vertex)
  501.     glDisable(GL_CULL_VERTEX_SGI);
  502. #endif
  503.     glDisable(GL_CULL_FACE);
  504.     glDisable(GL_LIGHTING);
  505.     glDisable(GL_DEPTH_TEST);
  506.  
  507.     glFlush();
  508.     SwapBuffers(hDC);
  509. }
  510.  
  511. /*****************************************************************/
  512.  
  513. void
  514. idleRedraw(void)
  515. {
  516.     if (!redrawContinue) {
  517.         idleFunc = NULL;
  518.     }
  519.     doRedraw();
  520. }
  521.  
  522. void
  523. redraw(void)
  524. {
  525.     if (!idleFunc) {
  526.     idleFunc = idleRedraw;
  527.     }
  528. }
  529.  
  530. /*****************************************************************/
  531.  
  532. /* these functions implement a simple trackball-like motion control */
  533. BOOL trackingMotion = FALSE;
  534. float lastPos[3];
  535. DWORD lastTime;
  536. int startX, startY;
  537.  
  538. void
  539. ptov(int x, int y, int width, int height, float v[3])
  540. {
  541.     float d, a;
  542.  
  543.     /* project x,y onto a hemi-sphere centered within width, height */
  544.     v[0] = (2.0F*x - width) / width;
  545.     v[1] = (height - 2.0F*y) / height;
  546.     d = (float) sqrt(v[0]*v[0] + v[1]*v[1]);
  547.     v[2] = (float) cos((M_PI/2.0F) * ((d < 1.0F) ? d : 1.0F));
  548.     a = 1.0F / (float) sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  549.     v[0] *= a;
  550.     v[1] *= a;
  551.     v[2] *= a;
  552. }
  553.  
  554. void
  555. startMotion(DWORD time, int button, int x, int y)
  556. {
  557.     if (button == 1) {
  558.     mode = MoveObject;
  559.     } else {
  560.     return;
  561.     }
  562.  
  563.     trackingMotion = TRUE;
  564.     redrawContinue = FALSE;
  565.     startX = x;
  566.     startY = y;
  567.     ptov(x, y, winWidth, winHeight, lastPos);
  568. }
  569.  
  570. void
  571. stopMotion(DWORD time, int button, int x, int y)
  572. {
  573.     if (button == 1 && mode == MoveObject) {
  574.     trackingMotion = FALSE;
  575.     } else {
  576.     return;
  577.     }
  578.  
  579.     if (startX != x || startY != y) {
  580.     redrawContinue = TRUE;
  581.     } else {
  582.     angle = 0.0F;
  583.     redrawContinue = FALSE;
  584.     }
  585.     if (!redrawContinue) {
  586.     mode = MoveNone;
  587.     }
  588.     redraw();
  589. }
  590.  
  591. void
  592. trackMotion(DWORD time, int x, int y)
  593. {
  594.     if (trackingMotion) {
  595.     float curPos[3], dx, dy, dz;
  596.  
  597.     ptov(x, y, winWidth, winHeight, curPos);
  598.  
  599.     dx = curPos[0] - lastPos[0];
  600.     dy = curPos[1] - lastPos[1];
  601.     dz = curPos[2] - lastPos[2];
  602.     angle = 90.0F * (float) sqrt(dx*dx + dy*dy + dz*dz);
  603.  
  604.     axis[0] = lastPos[1]*curPos[2] - lastPos[2]*curPos[1];
  605.     axis[1] = lastPos[2]*curPos[0] - lastPos[0]*curPos[2];
  606.     axis[2] = lastPos[0]*curPos[1] - lastPos[1]*curPos[0];
  607.  
  608.     lastPos[0] = curPos[0];
  609.     lastPos[1] = curPos[1];
  610.     lastPos[2] = curPos[2];
  611.     redraw();
  612.     }
  613. }
  614.  
  615. /*****************************************************************/
  616.  
  617. void
  618. setupPalette(HDC hDC)
  619. {
  620.     PIXELFORMATDESCRIPTOR pfd;
  621.     LOGPALETTE* pPal;
  622.     int pixelFormat = GetPixelFormat(hDC);
  623.     int paletteSize;
  624.  
  625.     DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
  626.     if (!(pfd.dwFlags & PFD_NEED_PALETTE ||
  627.       pfd.iPixelType == PFD_TYPE_COLORINDEX))
  628.     {
  629.     return;
  630.     }
  631.  
  632.     paletteSize = 1 << pfd.cColorBits;
  633.     pPal = (LOGPALETTE*)
  634.     malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
  635.     pPal->palVersion = 0x300;
  636.     pPal->palNumEntries = paletteSize;
  637.  
  638.     /* start with a copy of the current system palette */
  639.     (void) GetSystemPaletteEntries(hDC, 0, paletteSize, &pPal->palPalEntry[0]);
  640.  
  641.     {
  642.     /* fill in an RGBA color palette */
  643.     int redMask = (1 << pfd.cRedBits) - 1;
  644.     int greenMask = (1 << pfd.cGreenBits) - 1;
  645.     int blueMask = (1 << pfd.cBlueBits) - 1;
  646.     int i;
  647.  
  648.     for (i=0; i<paletteSize; ++i) {
  649.         pPal->palPalEntry[i].peRed =
  650.             (((i >> pfd.cRedShift) & redMask) * 255) / redMask;
  651.         pPal->palPalEntry[i].peGreen =
  652.             (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
  653.         pPal->palPalEntry[i].peBlue =
  654.             (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask;
  655.         pPal->palPalEntry[i].peFlags = 0;
  656.     }
  657.     }
  658.  
  659.     hPalette = CreatePalette(pPal);
  660.     free(pPal);
  661.  
  662.     if (hPalette) {
  663.     SelectPalette(hDC, hPalette, FALSE);
  664.     RealizePalette(hDC);
  665.     }
  666. }
  667.  
  668. void
  669. setupPixelformat(HDC hDC)
  670. {
  671.     PIXELFORMATDESCRIPTOR pfd = {
  672.     sizeof(PIXELFORMATDESCRIPTOR),    /* size of this pfd */
  673.     1,                /* version num */
  674.     PFD_DRAW_TO_WINDOW |        /* support window */
  675.     PFD_SUPPORT_OPENGL,        /* support OpenGL */
  676.     PFD_TYPE_RGBA,            /* color type */
  677.     8,                /* 8-bit color depth */
  678.     0, 0, 0, 0, 0, 0,        /* color bits (ignored) */
  679.     0,                /* no alpha buffer */
  680.     0,                /* alpha bits (ignored) */
  681.     0,                /* no accumulation buffer */
  682.     0, 0, 0, 0,            /* accum bits (ignored) */
  683.     0,                /* depth buffer (filled below)*/
  684.     0,                /* no stencil buffer */
  685.     0,                /* no auxiliary buffers */
  686.     PFD_MAIN_PLANE,            /* main layer */
  687.     0,                /* reserved */
  688.     0, 0, 0,            /* no layer, visible, damage masks */
  689.     };
  690.     int SelectedPixelFormat;
  691.     BOOL retVal;
  692.  
  693.     if (doubleBuffered) {
  694.         pfd.dwFlags |= PFD_DOUBLEBUFFER;
  695.     }
  696.  
  697.     if (depthBuffered) {
  698.     pfd.cDepthBits = 16;
  699.     }
  700.  
  701.     SelectedPixelFormat = ChoosePixelFormat(hDC, &pfd);
  702.     if (SelectedPixelFormat == 0) {
  703.     MessageBox(WindowFromDC(hDC), "ChoosePixelFormat failed\n", "Error",
  704.         MB_ICONERROR | MB_OK);
  705.     exit(1);
  706.     }
  707.  
  708.     retVal = SetPixelFormat(hDC, SelectedPixelFormat, &pfd);
  709.     if (retVal != TRUE) {
  710.     MessageBox(WindowFromDC(hDC), "SetPixelFormat failed", "Error",
  711.         MB_ICONERROR | MB_OK);
  712.     exit(1);
  713.     }
  714. }
  715.  
  716. LRESULT APIENTRY
  717. WndProc(
  718.     HWND hWnd,
  719.     UINT message,
  720.     WPARAM wParam,
  721.     LPARAM lParam)
  722. {
  723.     switch (message) {
  724.     case WM_CREATE:
  725.     hDC = GetDC(hWnd);
  726.     setupPixelformat(hDC);
  727.     setupPalette(hDC);
  728.     hGLRC = wglCreateContext(hDC);
  729.     wglMakeCurrent(hDC, hGLRC);
  730.     init();
  731.     return 0;
  732.     case WM_DESTROY:
  733.     if (hGLRC) {
  734.         wglMakeCurrent(NULL, NULL);
  735.         wglDeleteContext(hGLRC);
  736.     }
  737.     idleFunc = NULL;
  738.     ReleaseDC(hWnd, hDC);
  739.     PostQuitMessage(0);
  740.     return 0;
  741.     case WM_SIZE:
  742.     if (hGLRC) {
  743.         winWidth = (int) LOWORD(lParam);
  744.         winHeight = (int) HIWORD(lParam);
  745.         resize();
  746.         return 0;
  747.     }
  748.     case WM_PALETTECHANGED:
  749.     if (hPalette != NULL && (HWND) wParam != hWnd) {
  750.         UnrealizeObject(hPalette);
  751.         SelectPalette(hDC, hPalette, FALSE);
  752.         RealizePalette(hDC);
  753.         redraw();
  754.         return 0;
  755.     }
  756.     break;
  757.     case WM_QUERYNEWPALETTE:
  758.     if (hPalette != NULL) {
  759.         UnrealizeObject(hPalette);
  760.         SelectPalette(hDC, hPalette, FALSE);
  761.         RealizePalette(hDC);
  762.         redraw();
  763.         return TRUE;
  764.     }
  765.     break;
  766.     case WM_PAINT:
  767.     if (hGLRC) {
  768.         PAINTSTRUCT ps;
  769.         BeginPaint(hWnd, &ps);
  770.         redraw();
  771.         EndPaint(hWnd, &ps);
  772.         return 0;
  773.     }
  774.     break;
  775.     case WM_LBUTTONDOWN:
  776.     if (hGLRC) {
  777.         int x = ((int) LOWORD(lParam) << 16) >> 16;
  778.         int y = ((int) HIWORD(lParam) << 16) >> 16;
  779.         SetCapture(hWnd);
  780.         startMotion(0, 1, x, y);
  781.         return 0;
  782.     }
  783.     break;
  784.     case WM_LBUTTONUP:
  785.     if (hGLRC) {
  786.         int x = ((int) LOWORD(lParam) << 16) >> 16;
  787.         int y = ((int) HIWORD(lParam) << 16) >> 16;
  788.         ReleaseCapture();
  789.         stopMotion(0, 1, x, y);
  790.         return 0;
  791.     }
  792.     break;
  793.     case WM_MOUSEMOVE:
  794.     if (hGLRC) {
  795.         int x = ((int) LOWORD(lParam) << 16) >> 16;
  796.         int y = ((int) HIWORD(lParam) << 16) >> 16;
  797.         trackMotion(0, x, y);
  798.         break;
  799.     }
  800.     case WM_CHAR:
  801.     switch ((int)wParam) {
  802.     case VK_ESCAPE:
  803.         DestroyWindow(hWnd);
  804.         return 0;
  805.     case VK_SPACE:
  806.         objectIndex = objectIndex < NUM_OBJECTS-1 ? ++objectIndex : 0;
  807.         redraw();
  808.         return 0;
  809.     case 'a':
  810.         useVertexArray = !useVertexArray;
  811.         redraw();
  812.         return 0;
  813.     case 'c':
  814.         useFaceCull = !useFaceCull;
  815.         redraw();
  816.         return 0;
  817.     case 'f':
  818.         useFog = !useFog;
  819.         redraw();
  820.         return 0;
  821.     case 'h':
  822.         halfObject = !halfObject;
  823.         redraw();
  824.         return 0;
  825.     case 'l':
  826.         useLighting = !useLighting;
  827.         redraw();
  828.         return 0;
  829.     case 'o':
  830.         perspectiveProj = !perspectiveProj;
  831.         resize();
  832.         redraw();
  833.         return 0;
  834.     case 'p':
  835.         drawOutlines = !drawOutlines;
  836.         redraw();
  837.         return 0;
  838.     case 'v':
  839.         useVertexCull = !useVertexCull;
  840.         redraw();
  841.         return 0;
  842.     case 'i':
  843.         yOffset += Y_OFFSET_STEP;
  844.         redraw();
  845.         return 0;
  846.     case 'j':
  847.         xOffset -= X_OFFSET_STEP;
  848.         redraw();
  849.         return 0;
  850.     case 'k':
  851.         xOffset += X_OFFSET_STEP;
  852.         redraw();
  853.         return 0;
  854.     case 'm':
  855.         yOffset -= Y_OFFSET_STEP;
  856.         redraw();
  857.         return 0;
  858.     case 'r':
  859.         textureReplace = !textureReplace;
  860.         redraw();
  861.         return 0;
  862.     case 't':
  863.         textureEnabled = !textureEnabled;
  864.         redraw();
  865.         return 0;
  866.     case 'x':
  867.         useVertexLocking = !useVertexLocking;
  868.         redraw();
  869.         return 0;
  870.     default:
  871.         break;
  872.     }
  873.     break;
  874.     case WM_KEYDOWN:
  875.     switch ((int)wParam) {
  876.     case VK_DOWN:
  877.         --objectNumMajor;
  878.         redraw();
  879.         break;
  880.     case VK_UP:
  881.         ++objectNumMajor;
  882.         redraw();
  883.         break;
  884.     case VK_LEFT:
  885.         --objectNumMinor;
  886.         redraw();
  887.         break;
  888.     case VK_RIGHT:
  889.         ++objectNumMinor;
  890.         redraw();
  891.         break;
  892.     default:
  893.         break;
  894.     }
  895.     if (hGLRC) redraw();
  896.     return 0;
  897.     default:
  898.     break;
  899.     }
  900.  
  901.     /* Deal with any unprocessed messages */
  902.     return DefWindowProc(hWnd, message, wParam, lParam);
  903. }
  904.  
  905. int APIENTRY
  906. WinMain(
  907.     HINSTANCE hCurrentInst,
  908.     HINSTANCE hPreviousInst,
  909.     LPSTR lpszCmdLine,
  910.     int nCmdShow)
  911. {
  912.     WNDCLASS wndClass;
  913.     HWND hWnd;
  914.     MSG msg;
  915.  
  916.     /* Define and register the window class */
  917.     wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  918.     wndClass.lpfnWndProc = WndProc;
  919.     wndClass.cbClsExtra = 0;
  920.     wndClass.cbWndExtra = 0;
  921.     wndClass.hInstance = hCurrentInst;
  922.     wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  923.     wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  924.     wndClass.hbrBackground = NULL;
  925.     wndClass.lpszMenuName = NULL;
  926.     wndClass.lpszClassName = className;
  927.     RegisterClass(&wndClass);
  928.  
  929.     /* Figure out a default size for the window */
  930.     winWidth = GetSystemMetrics(SM_CYSCREEN) / 3;
  931.     winHeight = GetSystemMetrics(SM_CYSCREEN) / 3;
  932.  
  933.     /* Create a window of the previously defined class */
  934.     hWnd = CreateWindow(
  935.     className, windowName,
  936.     WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  937.     winX, winY, winWidth, winHeight,
  938.     NULL, NULL, hCurrentInst, NULL);
  939.  
  940.     /* Map the window to the screen */
  941.     ShowWindow(hWnd, nCmdShow);
  942.  
  943.     /* Force the window to repaint itself */
  944.     UpdateWindow(hWnd);
  945.  
  946.     /* Message loop */
  947.     while (1) {
  948.     while (idleFunc &&
  949.            PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == FALSE)
  950.     {
  951.         (*idleFunc)();
  952.     }
  953.     if (GetMessage(&msg, NULL, 0, 0) != TRUE) {
  954.         break;
  955.     }
  956.     TranslateMessage(&msg);
  957.     DispatchMessage(&msg);
  958.     }
  959.     return msg.wParam;
  960. }
  961.  
  962. 
  963.